package com.meilingcloud.biobank.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilingcloud.biobank.domain.SampleBackup;
import com.meilingcloud.biobank.domain.Tube;
import com.meilingcloud.biobank.domain.dto.SampleConfirmLocation;
import com.meilingcloud.biobank.mapper.TubeMapper;
import com.meilingcloud.biobank.service.ISampleBackupService;
import com.meilingcloud.biobank.service.ITubeService;
import com.meilingcloud.common.enums.SampStatue;
import com.meilingcloud.common.enums.StockState;
import com.meilingcloud.common.enums.TubeStatus;
import com.meilingcloud.common.exception.CustomException;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 冻存管 Service业务层处理
 *
 * @author chenl
 * @date 2021-03-05
 */
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Service
public class TubeServiceImpl extends ServiceImpl<TubeMapper, Tube> implements ITubeService {

    private final ISampleBackupService sampleBackupService;

    @Override
    public List<Tube> queryList(Long containerId) {
        List<Tube> tubes = this.list(new LambdaQueryWrapper<Tube>().eq(Tube::getContainerId, containerId));
        List<Long> sampBackupIds = tubes.stream().map(Tube::getSampBackupId).collect(Collectors.toList());
        List<SampleBackup> sampleBackups = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(sampBackupIds)) {
            sampleBackups = sampleBackupService.listByIds(sampBackupIds);
            sampleBackupService.handleResult(sampleBackups);
        }
        if (CollectionUtil.isNotEmpty(sampleBackups)) {
            List<SampleBackup> finalSampleBackups = sampleBackups;
            tubes.stream().map(item ->
                    finalSampleBackups.stream().filter(i -> ObjectUtil.equal(i.getSampBackupId(), item.getSampBackupId()))
                            .findFirst()
                            .map(i -> {
                                item.setSample(i);
                                return item;
                            }).orElse(null)).collect(Collectors.toList());
        }

        return tubes;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean confirmLocation(SampleConfirmLocation sampleConfirmLocation) {
        // 样本复份表 写入样本位置 更改样本状态
        List<SampleBackup> sampleBackups = sampleConfirmLocation.getSampleBackups();
        List<SampleBackup> sampleBackupList = sampleBackups.stream().map(item -> {
            item.setSampState(SampStatue.TO_IN.getCode());// 待入库
            return item;
        }).collect(Collectors.toList());
        sampleBackupService.updateBatchById(sampleBackupList);
        // 冻存管表 写入样本id 更改冻存管状态
        List<Tube> tubes = sampleConfirmLocation.getTubes();
        List<Tube> tubeList = tubes.stream().map(item ->
                        sampleBackups.stream()
                                .filter(i -> ObjectUtil.equal(item.getSampBackupId(), i.getSampBackupId()))
                                .findFirst()
                                .map(i -> {
                                    item.setTubeState(TubeStatus.OCCUPY.getCode());
                                    return item;
                                }).orElse(null))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        boolean result = this.updateBatchById(tubeList);
        return result;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean clearLocation(SampleConfirmLocation sampleConfirmLocation) {
        // 样本复份表 清除样本位置 更改样本状态
        List<SampleBackup> sampleBackups = sampleConfirmLocation.getSampleBackups();
        if (CollectionUtil.isEmpty(sampleBackups)) {
            throw new CustomException("未选择要清除位置的样本复份");
        }
        List<SampleBackup> sampleBackupList = sampleBackups.stream().map(item -> {
            item.setSampLocation("");
            if (StringUtils.equals(item.getSampState(), SampStatue.TO_IN.getCode())) {
                item.setSampState(SampStatue.VIRTUAL.getCode());// 虚拟
            }
            return item;
        }).collect(Collectors.toList());
        sampleBackupService.updateBatchById(sampleBackupList);
        // 冻存管表 清除样本id 更改冻存管状态
        List<Long> sampBackupIds = sampleBackups.stream().map(SampleBackup::getSampBackupId).collect(Collectors.toList());
        List<Tube> tubes = this.list(new LambdaQueryWrapper<Tube>().in(Tube::getSampBackupId, sampBackupIds));
        List<Tube> tubeList = tubes.stream().map(item -> {
            item.setSampBackupId(0L);
            item.setTubeState(TubeStatus.NORMAL.getCode());
            return item;
        }).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(tubeList)) {
            return this.updateBatchById(tubeList);
        } else {
            throw new CustomException("当前样本未设定位置");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeSampBackup(List<Long> sampBackupIds) {
        List<SampleBackup> sampleBackups = sampleBackupService.listByIds(sampBackupIds);
        long count = sampleBackups.stream().filter(s -> StringUtils.equals(s.getStockState(), StockState.PROCESS.getCode())).count();
        if (count > 0) {
            throw new CustomException("当前删除项中存在已在流程中的样本复份，不允许删除");
        }
        List<Tube> tubes = this.list(new LambdaQueryWrapper<Tube>().in(Tube::getSampBackupId, sampBackupIds));
        List<Tube> tubeList = tubes.stream().map(item -> {
            item.setSampBackupId(0L);
            return item;
        }).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(tubeList)) {
            this.updateBatchById(tubeList);
        }
        return sampleBackupService.removeByIds(sampBackupIds);
    }


}
